package code;

import java.io.File;
import java.io.IOException;
import java.security.InvalidParameterException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

/**
 * Photo base provides much of the common functionality between photo files and photo albums.
 * 
 * @author Adam
 */
public abstract class DateBasedFile implements IDateBasedFile {

	// static Fields ----------------------------------------------------------

	public static String		yyyyMM	= "yyyyMM"; // e.g. 201009

	// Fields -----------------------------------------------------------------

	private YearMonthDayExtra	ymde;

	private File				file;
	private String				nameOriginal;
	private String				nameNew;

	private DateFormat			format;
	private IPhotoAlbum			parent;

	// Constructors ----------------------------------------------------------

	public DateBasedFile(File file, IPhotoAlbum parentAlbum) {
		if (file == null) {
			throw new InvalidParameterException("file");
		}

		setFile(file);
		setNameOriginal(file.getName());
		setParent(parentAlbum);
	}

	public void initialiseDate(DateFormat format) {
		this.format = format;
		splitName();
	}

	// Getters ---------------------------------------------------------------

	@Override
	public boolean exists() {
		return file.exists();
	}

	/*
	 * (non-Javadoc)
	 * @see code.IDateBasedFile#getDateFromName()
	 */
	@Override
	public Date getDateFromName() {
		if ((getYear() == -1) || (getMonth() == -1) || (getDay() == -1) || (getExtra() == null)) {
			return null;
		}

		String dateString = String.format("%d-%d-%d", getYear(), getMonth(), getDay());
		SimpleDateFormat formatter = new SimpleDateFormat("yy-MM-dd");
		Date date = null;

		try {
			date = formatter.parse(dateString);
		}
		catch (ParseException e) {
			e.printStackTrace();
			throw new InvalidParameterException(e.getMessage());
		}

		return date;
	}

	/*
	 * (non-Javadoc)
	 * @see code.IDateBasedFile#getDay()
	 */
	@Override
	public int getDay() {
		return (ymde == null) ? -1 : ymde.getDay();
	}

	/*
	 * (non-Javadoc)
	 * @see code.IDateBasedFile#getExtra()
	 */
	@Override
	public String getExtra() {
		return (ymde == null) ? "" : ymde.getExtra();
	}

	/*
	 * (non-Javadoc)
	 * @see code.IDateBasedFile#getFileName()
	 */
	@Override
	public String getFileName() {
		try {
			return file.getCanonicalPath();
		}
		catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			return "";
		} // .getName()
	}

	/*
	 * (non-Javadoc)
	 * @see code.IDateBasedFile#getMonth()
	 */
	@Override
	public int getMonth() {
		return (ymde == null) ? -1 : ymde.getMonth();
	}

	/*
	 * (non-Javadoc)
	 * @see code.IDateBasedFile#getNameNew()
	 */
	@Override
	public String getNameNew() {
		return nameNew;
	}

	/*
	 * (non-Javadoc)
	 * @see code.IDateBasedFile#getParent()
	 */
	@Override
	public IPhotoAlbum getParent() {
		return parent;
	}

	/*
	 * (non-Javadoc)
	 * @see code.IDateBasedFile#getPath()
	 */
	@Override
	public String getPath() {
		return file.getPath();
	}

	/*
	 * (non-Javadoc)
	 * @see code.IDateBasedFile#getYear()
	 */
	@Override
	public int getYear() {
		return (ymde == null) ? -1 : ymde.getYear();
	}

	@Override
	public boolean isAlbum() {
		return file.isDirectory();
	}

	// Private Setters --------------------------------------------------------

	@Override
	public boolean isPhoto() {
		return file.isFile();
	}

	/**
	 * rename a file to another filename.
	 */
	public boolean renameTo(IPhotoAlbum destinationAlbum, String newFileName) {
		File destinationFile = new File(destinationAlbum.getFileName());
		File newFile = new File(destinationFile, newFileName);

		if (file.isFile() && file.renameTo(newFile)) {
			setFile(newFile);
			setParent(destinationAlbum);
			return true;
		}

		return false;
	}

	// Public Methods ---------------------------------------------------------

	public void setFile(File file) {
		this.file = file;
	}

	/**
	 * sets the parent album. A null parent is a perfectly valid case and indicates that it is a root folder.
	 * 
	 * @param parent album.
	 */
	public void setParent(IPhotoAlbum parent) {
		this.parent = parent;
	}

	// Protected --------------------------------------------------------------

	protected File getFile() {
		return file;
	}

	protected String getNameOriginal() {
		return nameOriginal;
	}

	protected void setNameNew(String nameNew) {
		this.nameNew = nameNew;
	}

	protected void setNameOriginal(String nameOriginal) {
		this.nameOriginal = nameOriginal;
		this.nameNew = nameOriginal; // if we're resetting the original name, then also update the new name
	}

	/**
	 * Split the originalName up into it's year, month, day and extra components. If things aren't going swimmingly, then set them to -1.
	 * 
	 * @return true if a successful value was obtained.
	 */
	private boolean splitName() {
		assert (ymde != null);

		ymde = new YearMonthDayExtra(nameOriginal, format);

		return ymde.valid();
	}
}